package com.xuecheng.learning.listener;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.base.constant.LearningChooseCourseStatusConstant;
import com.xuecheng.base.constant.OrderPayRecordStatusConstant;
import com.xuecheng.base.constant.RabbitMQConstant;
import com.xuecheng.base.exception.CommonError;
import com.xuecheng.base.exception.XCPlusBaseException;
import com.xuecheng.learning.model.po.XcChooseCourse;
import com.xuecheng.learning.model.po.XcCourseTables;
import com.xuecheng.learning.service.IXcChooseCourseService;
import com.xuecheng.learning.service.IXcCourseTablesService;
import com.xuecheng.message.sdk.model.po.MqMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * @author 勾新杰
 * @version 1.0
 * @description:
 * @date 2025/3/8 17:20
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PayResultNotifyListener {

    private final IXcChooseCourseService xcChooseCourseService;

    private final IXcCourseTablesService xcCourseTablesService;

    /**
     * 支付结果通知
     * @param message 业务数据
     */
    @Transactional
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = RabbitMQConstant.QUEUE_PAY_RESULT_LEARNING, durable = "true"),
            exchange = @Exchange(value = RabbitMQConstant.EXCHANGE_PAY_RESULT_TOPIC, type = ExchangeTypes.TOPIC),
            key = RabbitMQConstant.ROUTING_KEY_PAY_RESULT_TOPIC
    ))
    public void listenPaySuccessNotify(MqMessage message) {
        log.debug("收到支付结果通知:{}", message);
        // 1. 接收支付结果通知，获取业务数据：选课id和支付状态
        Long id = Long.valueOf(message.getBusinessKey1());
        String payStatus = message.getBusinessKey2();
        // 2. 如果支付成功，则更新选课记录状态为成功、添加到我的课程表
        if (OrderPayRecordStatusConstant.PAID.equals(payStatus)) {
            // 2.0 注意并发问题，这里采用数据库的行级锁的排他锁，也可以抽离成一个方法，在抽离的这个方法上面加@Transactional但是要注意事务失效问题
            XcChooseCourse xcChooseCourse = xcChooseCourseService.getByIdForUpdate(id);
            // 2.1 幂等性判断，已经支付成功了的话不必再更新
            if (xcChooseCourse.getStatus().equals(LearningChooseCourseStatusConstant.CHOOSE_COURSE_SUCCESS)) return;
            // 2.2 更新选课记录状态为成功
            xcChooseCourseService.lambdaUpdate()
                    .eq(XcChooseCourse::getId, id)
                    .set(XcChooseCourse::getStatus, LearningChooseCourseStatusConstant.CHOOSE_COURSE_SUCCESS)
                    .update();
            // 2.3 添加到我的课程表
            xcCourseTablesService.remove(new LambdaQueryWrapper<XcCourseTables>()
                    .eq(XcCourseTables::getUserId, xcChooseCourse.getUserId())
                    .eq(XcCourseTables::getCourseId, xcChooseCourse.getCourseId()));
            XcCourseTables xcCourseTables = BeanUtil.copyProperties(xcChooseCourse, XcCourseTables.class);
            LocalDateTime now = LocalDateTime.now();
            xcCourseTables
                    .setChooseCourseId(xcChooseCourse.getId())
                    .setCourseType(xcChooseCourse.getOrderType())
                    .setCreateDate(now)
                    .setValidtimeStart(now)
                    .setValidtimeEnd(now.plusDays(xcChooseCourse.getValidDays()))
                    .setUpdateDate(now);
            boolean save = xcCourseTablesService.save(xcCourseTables);
            if (!save) XCPlusBaseException.cast(CommonError.FAILED_INSERT_TO_DATABASE);
        }
    }
}
